Option Strict On
Option Explicit On

'Copyright (c) 2007-2010, William Severance, Jr., WESNet Designs
'All rights reserved.

'Redistribution and use in source and binary forms, with or without modification, are permitted
'provided that the following conditions are met:

'Redistributions of source code must retain the above copyright notice, this list of conditions
'and the following disclaimer.

'Redistributions in binary form must reproduce the above copyright notice, this list of conditions
'and the following disclaimer in the documentation and/or other materials provided with the distribution.

'Neither the name of William Severance, Jr. or WESNet Designs may be used to endorse or promote
'products derived from this software without specific prior written permission.

'Disclaimer: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
'            OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
'            AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE
'            FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
'            LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
'            INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
'            OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
'            IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

'Although I will try to answer questions regarding the installation and use of this software when
'such questions are submitted via e-mail to the below address, no promise of further
'support or enhancement is made nor should be assumed.

'Developer Contact Information:
'     William Severance, Jr.
'     WESNet Designs
'     679 Upper Ridge Road
'     Bridgton, ME 04009
'     Phone: 207-647-9375
'     E-Mail: bill@wesnetdesigns.com
'     Website: www.wesnetdesigns.com

Imports DotNetNuke.Common
Imports DotNetNuke.Services.Mail
Imports DotNetNuke.Security
Imports System.Reflection
Imports System.ComponentModel
Imports System.Xml
Imports System.Text.RegularExpressions
Imports System.IO

Namespace WESNet.DNN.Modules.EPrayer
  Public Class Utilities
    Public Shared Function AddHost(ByVal URL As String) As String
      Dim result As String
      Dim host As String = HttpContext.Current.Request.ServerVariables("HTTP_HOST").TrimEnd("/"c)

      If Not URL.ToLower.Contains(host.ToLower) Then
        If Not URL.StartsWith("/") Then URL = "/" & URL
        result = host & URL
      Else
        result = URL
      End If
      Return AddHTTP(result)
    End Function

    Public Shared Function TruncateString(ByVal Text As String, ByVal MaxLength As Integer) As String
      Dim s As String = String.Empty
      Dim p As Integer
      If Not String.IsNullOrEmpty(Text) Then
        Text = StripHTMLTags(Text)
        If Len(Text) > MaxLength Then
          p = Text.LastIndexOfAny(New Char() {"."c, " "c, Chr(13)}, MaxLength - 1)
          If p > 0 Then s = Text.Substring(0, p) & "..."
        Else
          s = Text
        End If
      End If
      Return s
    End Function

    Public Shared Function StripImageTags(ByVal Text As String) As String
      Dim rgx As New Regex("<img[^>]*>", RegexOptions.IgnoreCase)
      Return rgx.Replace(Text, "")
    End Function

    Public Shared Function StripAnchorTags(ByVal Text As String) As String
      Dim rgx As New Regex("<a\s+href='(?<href>[^']*)'[^>]*>(?<inner>[^>]*)</a>", RegexOptions.IgnoreCase)
      Return rgx.Replace(Text, "${inner} (${href})")
    End Function

    Public Shared Function ReplaceBreaks(ByVal Text As String) As String
      Return Regex.Replace(Text, "<\s*br\s*/?\s*>", vbCrLf, RegexOptions.IgnoreCase)
    End Function

    Public Shared Function ReplacevbCrlf(ByVal Text As String) As String
      Text = Text.Replace(vbCrLf, "<br />")
      Return Text.Replace(vbCr, "<br />")
    End Function

    Public Shared Function StripAllHtmlTags(ByVal Text As String) As String
      Return Regex.Replace(Text, "<[^>]*>", "")
    End Function

    Public Shared Function StripHTMLTags(ByVal Text As String) As String
      Text = New DotNetNuke.Security.PortalSecurity().InputFilter(Text, PortalSecurity.FilterFlag.NoScripting)
      Text = Regex.Replace(Text, "&nbsp;", " ")
      Text = ReplaceBreaks(Text)
      Text = StripAnchorTags(Text)
      Text = StripAllHtmlTags(Text)
      Text = StripImageTags(Text)
      'Text = Regex.Replace(Text, "<b>", "")
      'Text = Regex.Replace(Text, "</b>", "")
      'Text = Regex.Replace(Text, "<i>", "")
      'Text = Regex.Replace(Text, "</i>", "")
      Text = Regex.Replace(Text, """", "'")
      'Text = Regex.Replace(Text, "/>", "")
      Text = Regex.Replace(Text, "&lt;", "<")
      Text = Regex.Replace(Text, "&gt;", ">")
      'Text = Regex.Replace(Text, "<p>", "")
      'Text = Regex.Replace(Text, "</p>", "")
      Return Text
    End Function

    Public Shared Function CleanMultiLineHTML(ByVal Text As String) As String
      Text = Regex.Replace(Text, "<b\s*/?><p>", "<p>")
      Text = Regex.Replace(Text, "<b\s*/?></p>", "</p>")
      Text = Regex.Replace(Text, "<p><br\s*/?>", "<p>")
      Text = Regex.Replace(Text, "</p>(<br\s*/?>)+", "</p>")
      Text = Regex.Replace(Text, "<p>\s*</p>", "")
      Return Text
    End Function

    Public Shared Sub LocalizeGridView(ByVal gv As GridView, ByVal ResourceFile As String)
      Dim key As String
      Dim localizedText As String
      Dim pi As System.Reflection.PropertyInfo

      For Each col As DataControlField In gv.Columns
        key = col.HeaderText
        If key <> "" Then
          localizedText = Localization.GetString(key & ".Header", ResourceFile)
          If localizedText <> "" Then
            col.HeaderText = localizedText
          End If
        End If

        'Localize text of Cancel, Delete, Edit, Insert, Select, New, Update buttons
        If TypeOf col Is CommandField Then
          Dim cmdField As CommandField = DirectCast(col, CommandField)
          For Each cmdName As String In New String() {"Cancel", "Delete", "Edit", "Insert", "Select", "New", "Update"}
            pi = cmdField.GetType.GetProperty(cmdName & "Text", GetType(String))
            key = CType(pi.GetValue(cmdField, Nothing), String)
            If Not String.IsNullOrEmpty(key) Then
              localizedText = Localization.GetString(key & ".CommandText", ResourceFile)
              If localizedText <> "" Then
                pi.SetValue(cmdField, localizedText, Nothing)
              End If
            End If
          Next
        End If
      Next
    End Sub

    Public Shared Function GetSettingValue(Of T)(ByVal setting As Object, ByVal defaultvalue As T) As T
      If setting Is Nothing Then
        Return defaultvalue
      Else
        If TypeOf defaultvalue Is System.Enum Then
          Try
            Return CType([Enum].Parse(GetType(T), CType(setting, String)), T)
          Catch ex As ArgumentException
            Return defaultvalue
          End Try
        ElseIf TypeOf defaultvalue Is System.DateTime Then
          Dim objDateTime As Object
          Try
            objDateTime = DateTime.Parse(CType(setting, String))
          Catch ex As FormatException
            Dim dt As DateTime
            If Not DateTime.TryParse(CType(setting, String), Globalization.DateTimeFormatInfo.InvariantInfo, Globalization.DateTimeStyles.None, dt) Then
              dt = DateTime.Now
            End If
            objDateTime = dt
          End Try
          Return CType(objDateTime, T)
        Else
          Try
            Return CType(setting, T)
          Catch ex As InvalidCastException
            Return defaultvalue
          End Try
        End If
      End If
    End Function

    Public Shared Function FormatPrayerOrPraise(ByVal IsPraise As Boolean, ByVal LocalSharedResourceFile As String) As String
      If IsPraise Then
        Return Localization.GetString("Praise_Report", LocalSharedResourceFile)
      Else
        Return Localization.GetString("Prayer_Request", LocalSharedResourceFile)
      End If
    End Function

    Public Shared Function LocalizeSharedResource(ByVal s As String, ByVal LocalSharedResourceFile As String) As String
      Return Localization.GetString(s, LocalSharedResourceFile)
    End Function

    'Public Shared Sub SerializeObjectToXML(ByVal sb As StringBuilder, ByVal obj As Object)
    '    Dim LoweredName As String
    '    Dim Value As Object
    '    Dim StringValue As String
    '    Dim Converter As TypeConverter
    '    Dim props As ArrayList = CBO.GetPropertyInfo(obj.GetType)

    '    For Each p As PropertyInfo In props
    '        If p.CanWrite() And p.CanWrite() Then
    '            LoweredName = p.Name.ToLower
    '            Value = p.GetValue(obj, Nothing)
    '            If Value Is Nothing Then
    '                StringValue = String.Empty
    '            Else
    '                Converter = TypeDescriptor.GetConverter(p.PropertyType)
    '                StringValue = Converter.ConvertToString(Value)
    '            End If
    '            sb.Append("<")
    '            sb.Append(LoweredName)
    '            sb.Append(">")
    '            sb.Append(DotNetNuke.Common.Utilities.XmlUtils.XMLEncode(StringValue))
    '            sb.Append("</")
    '            sb.Append(LoweredName)
    '            sb.Append(">")
    '        End If
    '    Next
    'End Sub

    'Public Shared Sub DeserializeObjectFromXML(ByVal Node As XmlNode, ByVal obj As Object)
    '    Dim PropertyName As String
    '    Dim StringValue As String
    '    Dim Converter As TypeConverter
    '    Dim PI As PropertyInfo
    '    For Each Item As XmlElement In Node
    '        PropertyName = Item.Name
    '        StringValue = Item.InnerText
    '        PI = obj.GetType.GetProperty(PropertyName)
    '        If Not PI Is Nothing AndAlso PI.CanWrite() AndAlso PI.CanRead() Then
    '            Converter = TypeDescriptor.GetConverter(PI.PropertyType)
    '            PI.SetValue(obj, Converter.ConvertFromString(StringValue), Nothing)
    '        End If
    '    Next
    'End Sub

    Public Shared Function GetPropertyValue(ByVal Container As Object, ByVal PropertyName As String) As Object
      Dim MethInfo As MethodInfo = Nothing
      Dim FldInfo As FieldInfo = Nothing
      Dim PropInfo As PropertyInfo = Nothing

      PropertyName = (PropertyName.Replace("-"c, "."c)).TrimStart("."c)

      Dim obj As Object = Container
      Dim objType As Type = obj.GetType
      Dim idx1 As Integer = 0
      Dim names As String() = PropertyName.Split("."c)
      Dim name As String
      Do While idx1 <= names.Length - 1
        name = names(idx1)
        Dim MbrInfo As MemberInfo() = objType.GetMember(name) ', BindingFlags.GetProperty Or BindingFlags.GetField)
        If MbrInfo Is Nothing OrElse MbrInfo.Length = 0 Then
          obj = Nothing
          Exit Do
        End If
        ' Note: MbrInfo will contain more than one item when an object has overridden or shadows a base class property.
        ' Always take the last MemberInfo collection item
        Dim lastItemCount = MbrInfo.Count - 1
        If MbrInfo(lastItemCount).MemberType = MemberTypes.Property Then
          PropInfo = CType(MbrInfo(lastItemCount), PropertyInfo)
          objType = PropInfo.PropertyType
          MethInfo = PropInfo.GetGetMethod
          obj = MethInfo.Invoke(obj, Nothing)
        ElseIf MbrInfo(lastItemCount).MemberType = MemberTypes.Field Then
          FldInfo = CType(MbrInfo(lastItemCount), FieldInfo)
          objType = FldInfo.FieldType
          obj = FldInfo.GetValue(obj)
        End If
        idx1 += 1
      Loop
      Return obj
    End Function

    Public Shared Function GetPropertyText(ByVal Container As Object, ByVal PropertyName As String, ByVal FormatString As String) As String
      Dim obj As Object = GetPropertyValue(Container, PropertyName)
      Dim s As String
      If obj Is Nothing OrElse Not TypeDescriptor.GetConverter(obj).CanConvertTo(GetType(String)) Then
        s = String.Empty
      Else
        If String.IsNullOrEmpty(FormatString) Then
          s = Convert.ToString(obj)
        Else
          s = String.Format(FormatString, obj)
        End If
      End If
      Return s
    End Function

    Public Shared Function OpenXMLTemplate(ByVal TemplateFileRoot As String, ByRef Language As String) As System.Xml.XPath.XPathDocument

      Dim TemplateFile As String
      Dim cacheKey As String
      Dim doc As XPath.XPathDocument
      Dim ps As PortalSettings = DotNetNuke.Common.GetPortalSettings()
      Dim PortalID As Integer = 0
      If Not ps Is Nothing Then PortalID = ps.PortalId

      'Get the filename for the userlanguage version of the template file
      TemplateFile = GetTemplateFileName(TemplateFileRoot, Language)

      If String.IsNullOrEmpty(ApplicationPath) Then
        cacheKey = TemplateFile.ToLower & PortalID.ToString
      Else
        cacheKey = TemplateFile.Replace(ApplicationPath, "").ToLower & PortalID.ToString
      End If

      'Attempt to get the resources from the cache
      doc = CType(DataCache.GetCache(cacheKey), XPath.XPathDocument)

      If doc Is Nothing Then
        TemplateFile = HttpContext.Current.Server.MapPath(TemplateFile)
        If File.Exists(TemplateFile) Then
          doc = New XPath.XPathDocument(TemplateFile)
          If Not doc Is Nothing Then
            DataCache.SetCache(cacheKey, doc)
          End If
        Else
          Throw New System.IO.IOException("Template file " & TemplateFile & " does not exist.")
        End If
      End If

      Return doc

    End Function

    Private Shared Function GetTemplateFileName(ByVal TemplateFileRoot As String, ByVal Language As String) As String

      Dim TemplateFile As String
      Dim TemplateFileExtension As String

      Dim DefaultLanguage As String = ""
      Dim ps As PortalSettings = DotNetNuke.Common.GetPortalSettings()
      If Not ps Is Nothing Then DefaultLanguage = ps.DefaultLanguage.ToLower

      If String.IsNullOrEmpty(Language) Then Language = System.Threading.Thread.CurrentThread.CurrentCulture.ToString.ToLower

      If Language = "" Then Language = DefaultLanguage

      TemplateFileExtension = System.IO.Path.GetExtension(TemplateFileRoot)

      If Language = Localization.SystemLocale.ToLower Or Language = "" Then
        If TemplateFileExtension = ".xml" Then
          TemplateFile = TemplateFileRoot
        Else
          TemplateFile = TemplateFileRoot & ".xml"
        End If
      Else
        If TemplateFileExtension = ".xml" Then
          TemplateFile = TemplateFileRoot.Replace(".xml", "." + Language + ".xml")
        Else
          TemplateFile = TemplateFileRoot + "." + Language + ".xml"
        End If
      End If
      Return TemplateFile
    End Function

    Public Shared Function GetTemplateFileNames(ByVal TemplatePath As String) As String()
      Dim TemplateFile As String = Path.GetFileNameWithoutExtension(TemplatePath)
      TemplatePath = Path.GetDirectoryName(TemplatePath)
      TemplatePath = HttpContext.Current.Server.MapPath(TemplatePath)

      Dim TemplateFiles() As String = Directory.GetFiles(TemplatePath, TemplateFile & "*.xml")
      Dim UpperBound As Integer = TemplateFiles.Length - 1
      Dim TemplateFileNames(UpperBound) As String
      For i As Integer = 0 To UpperBound
        TemplateFileNames(i) = Path.GetFileName(TemplateFiles(i))
      Next
      Return TemplateFileNames
    End Function

    Public Shared Function GetTemplateNames(ByVal XPathNav As XPath.XPathNavigator) As String()
      If Not XPathNav Is Nothing Then
        Dim Templates As XPath.XPathNodeIterator = XPathNav.Select("Templates/Template")
        Dim UpperBound As Integer = Templates.Count - 1
        If UpperBound < 0 Then
          Return New String() {}
        Else
          Dim TemplateNames(UpperBound) As String
          For i As Integer = 0 To Templates.Count - 1
            Templates.MoveNext()
            TemplateNames(i) = Templates.Current.GetAttribute("Name", "")
          Next
          Return TemplateNames
        End If
      Else
        Return New String() {}
      End If

    End Function

    Public Shared Function GetStyleNames(ByVal XPathNav As XPath.XPathNavigator, ByVal TemplateName As String) As String()
      If Not XPathNav Is Nothing AndAlso Not String.IsNullOrEmpty(TemplateName) Then
        Dim Styles As XPath.XPathNodeIterator = XPathNav.Select("Templates/Template[@Name='" & TemplateName & "']/Styles/Body")
        Dim UpperBound As Integer = Styles.Count - 1
        If UpperBound < 0 Then
          Return New String() {}
        Else
          Dim StyleNames(UpperBound) As String
          For i As Integer = 0 To UpperBound
            Styles.MoveNext()
            StyleNames(i) = Styles.Current.GetAttribute("Style", "")
          Next
          Return StyleNames
        End If
      Else
        Return New String() {}
      End If
    End Function

    Public Shared Sub DistributionCBLEnableViewable(ByVal cbl As CheckBoxList, ByVal ViewableDistributions As Integer)
      Dim n As Integer = 1
      For Each li As ListItem In cbl.Items
        li.Enabled = (ViewableDistributions And Convert.ToInt32(li.Value)) <> 0
      Next
    End Sub

    Public Shared Sub DistributionCBLSet(ByVal cbl As CheckBoxList, ByVal Distributions As Integer)
      Dim n As Integer = 1
      Dim li As ListItem
      If Distributions = 0 Then
        DistributionCBLSetAll(cbl)
      Else
        cbl.ClearSelection()
        Do While Distributions >= n
          If (Distributions And n) <> 0 Then
            li = cbl.Items.FindByValue(n.ToString)
            If Not li Is Nothing AndAlso li.Enabled Then li.Selected = True
          End If
          n *= 2
        Loop
      End If
    End Sub

    Public Shared Function DistributionCBLGet(ByVal cbl As CheckBoxList, ByVal AllCheckedReturnsZero As Boolean) As Integer
      Dim n As Integer = 0
      For Each li As ListItem In cbl.Items
        If li.Selected And li.Enabled Then
          n = n Or Convert.ToInt32(li.Value)
        Else
          AllCheckedReturnsZero = False
        End If
      Next
      If AllCheckedReturnsZero Then
        Return 0
      Else
        Return n
      End If
    End Function

    Public Shared Sub DistributionCBLSetAll(ByVal cbl As CheckBoxList)
      For Each li As ListItem In cbl.Items
        li.Selected = True
      Next
    End Sub

    Public Shared Sub DistributionCBLClearAll(ByVal cbl As CheckBoxList)
      cbl.ClearSelection()
    End Sub

    Public Shared Function IsDistributionBitSet(ByVal Distribution As Integer, ByVal DistributionMask As Integer) As Boolean
      Return (Distribution And DistributionMask) <> 0
    End Function

    Public Shared Function IsDistributionCBLAllChecked(ByVal cbl As CheckBoxList) As Boolean
      Dim i As Integer

      If cbl Is Nothing OrElse cbl.Items.Count = 0 Then Return False

      Do While i < cbl.Items.Count
        If Not cbl.Items(i).Selected Then Return False
        i += 1
      Loop
      Return True
    End Function
  End Class
End Namespace


